home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / MISC / AUDIO.ZIP / FX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-11  |  23.4 KB  |  703 lines

  1. /*
  2.     FX.C - audio effects for AD1848-based PC soundcards.
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #include <dos.h>
  9. #include <conio.h>
  10. #include "1848.h"
  11.  
  12. #define BFSZ        4096    /* main delay buffer */
  13. #define MAX_XTAB    512     /* crossfade lookup table size for pitch change */
  14. #define NA          0.0     /* param not applicable */
  15.  
  16. #ifndef TRUE
  17. #define TRUE        1
  18. #define FALSE       0
  19. #endif
  20.  
  21. /* macros for pitch_change delay index manipulation */
  22. #define inc_index(x)        x = (x + 1) & (BFSZ - 1)
  23. #define inc_indexes(x1,x2)  { x2 = x1; inc_index(x1); }
  24.  
  25. /* key eye on human every once in a while in all effect routines */
  26. #define SCAN_HUMAN          0x40000L    /* sets rate of checking for key */
  27. #define check_human()       {                           \
  28.                                 if(scan-- == 0)  {      \
  29.                                     chk_keystroke();    \
  30.                                     scan = SCAN_HUMAN;  \
  31.                                 }                       \
  32.                             }
  33.                             
  34. /* program description struct */
  35. struct program {
  36.     char *name;         /* ASCII name of program */
  37.     void (*vec)(struct program *p);
  38.     double dry_mix;     /* dry (unaffected) signal mix */
  39.     double wet_mix;     /* wet (affected) signal mix */
  40.     double feedback;    /* feedback */
  41.     double rate;        /* usually rate of sweep */
  42.     double depth;       /* width of sweep */
  43.     double delay;       /* fixed delay factor (base pitch for phaser) */
  44. } program;
  45.  
  46. /* handy typedefs */
  47. typedef union bw {
  48.     unsigned char b[2];
  49.     int w;
  50. } bw;
  51. typedef union wl {
  52.     unsigned int w[2];
  53.     long l;
  54. } wl;
  55.     
  56. /* protos */
  57. void thru(struct program *p);
  58. void noise_gate(struct program *p);
  59. void flange_chorus(struct program *p);
  60. void pitch_change(struct program *p);
  61. void phase_shift(struct program *p);
  62. void chk_keystroke(void);
  63. void usage(void);
  64. void init_1848(int samprate, int mic, int gain);
  65. void wr_reg(int reg, int val);
  66. int  rd_reg(int reg);
  67.  
  68. /* table of programs (it's very easy to modify and add programs) */
  69. struct program programs[] = {
  70.     /*  Name/vector      Dry     Wet   Feedback Rate    Depth   Delay */
  71.     { "Echoes",
  72.         flange_chorus,  0.999,  0.999,  0.7,    0.0,    0.0,    250.0},
  73.     { "Slow flange",
  74.         flange_chorus,  0.999,  0.999,  0.0,    2.0,    6.0,    0.0},
  75.     { "Slow invert flange with feedback",
  76.         flange_chorus,  0.999,  -0.999, -0.7,   2.0,    6.0,    0.0},
  77.     { "Slow chorus",
  78.         flange_chorus,  0.999,  0.999,  0.0,    11.0,   20.0,   20.0},
  79.     { "Cheesy \"take me to your leader\" robot voice",
  80.         flange_chorus,  0.0,    0.999,  0.75,   0.0,    0.0,    12.5},
  81.     { "Crazy pitch bend chorus",
  82.         flange_chorus,  0.999,  0.999,  0.3,    150.0,  40.0,   40.0},
  83.     { "Darth",
  84.         pitch_change,   0.0,    0.999,  0.0,    -0.35,  25.0,   0.0},
  85.     { "Major third up",
  86.         pitch_change,   0.999,  0.999,  0.0,    0.2599, 35.0,   0.0},
  87.     { "Octave up",
  88.         pitch_change,   0.999,  0.999,  0.0,    1.0,    40.0,   0.0},
  89.     { "Munchkins on helium",
  90.         pitch_change,   0.0,    0.999,  0.4,    0.3348, 35.0,   0.0},
  91.     { "Descending echoes",
  92.         pitch_change,   0.0,    0.999,  0.5,    -0.2,   35.0,   120.0},
  93.     { "Ascending echoes",
  94.         pitch_change,   0.0,    0.999,  0.4,    0.2599, 35.0,   120.0},
  95.     { "Phase shift",
  96.         phase_shift,    0.999,  0.999,  0.0,    1.0,    4.0,    100.0},
  97.     { "Slow invert phase shift with feedback",
  98.         phase_shift,    0.999,  -0.999, -0.6,   0.2,    6.0,    100.0},
  99.     { "Noise gate",
  100.         noise_gate,     NA,     NA,     NA,     500.0,  0.05,   NA},
  101.     { "Straight Thru",
  102.         thru,           NA,     NA,     NA,     NA,     NA,     NA},
  103. };
  104. #define NPROGS (sizeof(programs) / sizeof(struct program))
  105.  
  106. /* globals */
  107. unsigned int SampleRate;            /* sample rate set by init_1848 */
  108. double Buf[BFSZ];                   /* buffer used by delay based effects */
  109.  
  110.  
  111. /*
  112.                                 main
  113. */
  114. void
  115. main(int argc, char **argv)
  116. {
  117.     int patch,samprate,gain;
  118.     struct program *p;
  119.     
  120.     /* make sure we got reasonable # of command line params */
  121.     if(argc < 2 || argc > 4) usage();
  122.     
  123.     /* get pointer to selected program */
  124.     patch = atoi(argv[1]);
  125.     if(patch < 0 || patch > NPROGS)
  126.         usage();
  127.     p = &programs[patch];
  128.     
  129.     /* see if sample rate specified (default to 16k) */
  130.     if(argc > 2)
  131.         samprate = atoi(argv[2]);
  132.     else
  133.         samprate = 16;
  134.  
  135.     /* see if source/gain spec'd */
  136.     if(argc > 3)
  137.         gain = atoi(argv[3]);
  138.     else
  139.         gain = 0x17;                /* default: select mic with gain of 15 */
  140.         
  141.     /* init hardware */
  142.     init_1848(samprate,gain & 0x10, gain & 0xf);
  143.  
  144.     /* call the routine spec'd in the program */
  145.     printf("\nPatch %d: %s\n",patch,p->name);
  146.     (*p->vec)(p);
  147.     /* never returns */
  148. }
  149.  
  150. /*
  151.                                 thru
  152.     
  153.     Simply reads 1848 input and routes directly thru to output.
  154.     Useful for setting gain for minimum noise and distortion.
  155.     All program parms ignored.
  156. */
  157. void
  158. thru(struct program *p)
  159. {
  160.     bw data;
  161.     long scan = 0;
  162.  
  163.     data.w = (int)p->dry_mix;               /* quiet the compiler */
  164.         
  165.     /* disable interrupts, go to it */
  166.     disable();
  167.     while(1) {
  168.         while((inp(SR) & 0x20) == 0);       /* wait for input ready */
  169.         data.b[0] = inp(PDR);               /* read input from chip */
  170.         data.b[1] = inp(PDR);
  171.         
  172.         while((inp(SR) & 0x2) == 0);        /* wait for output ready */
  173.         outp(PDR,data.b[0]);                /* write output to chip */
  174.         outp(PDR,data.b[1]);
  175.         
  176.         check_human();                      /* check on human every so often */
  177.     }
  178. }
  179.  
  180.  
  181. /*
  182.                                 noise_gate
  183.  
  184.     Super simple noise gate to demonstrate how much of the hiss
  185.     comes directly from the ADC on this card, but how quiet the
  186.     DACs are by comparison.
  187.         
  188.     Only parms are:
  189.         rate        decay time in ms
  190.         depth       threshold for turn on
  191. */
  192. void
  193. noise_gate(struct program *p)
  194. {
  195.     double inval,decay_fac,gain = 0;
  196.     bw data;
  197.     long scan = 0;
  198.  
  199.     /* calculate decay factor for 20db atten in spec'd time */
  200.     decay_fac = pow(10.0,1.0 / ((p->rate / 1000.0) * (double)SampleRate));
  201.     decay_fac = 1.0 / decay_fac;
  202.         
  203.     /* disable interrupts, go to it */
  204.     disable();
  205.     while(1) {
  206.         while((inp(SR) & 0x20) == 0);       /* wait for input ready */
  207.         data.b[0] = inp(PDR);               /* read input from chip */
  208.         data.b[1] = inp(PDR);
  209.  
  210.         inval = (double)data.w;
  211.         if(inval > p->depth)                /* see if we crossed threshold */
  212.             gain = 1.0;                     /* turn gate on */
  213.         data.w = (int)(inval * gain);
  214.         
  215.         while((inp(SR) & 0x2) == 0);        /* wait for output ready */
  216.         outp(PDR,data.b[0]);                /* write output to chip */
  217.         outp(PDR,data.b[1]);
  218.         
  219.         gain *= decay_fac;                  /* adjust attenuation */
  220.         
  221.         check_human();                      /* check on human every so often */
  222.     }
  223. }
  224.  
  225.         
  226. /*
  227.                                 flange_chorus
  228.     
  229.     Does flanging/chorusing family of effects based on a single
  230.     varying delay.
  231.     
  232.     dry_mix     mix of unaffected signal (-0.999 to 0.999)
  233.     wet_mix     mix of affected signal (-0.999 - 0.999)
  234.     feedback    amount of recirculation (-0.9 - 0.9)
  235.     rate        rate of delay change in millisecs per sec
  236.     sweep       sweep range in millisecs
  237.     delay       fixed additional delay in millisecs
  238. */
  239. void
  240. flange_chorus(struct program *p)
  241. {
  242.     int fp,ep1,ep2;
  243.     int step,depth,delay,min_sweep,max_sweep;
  244.     double inval,outval,ifac = 65536.0;
  245.     long scan = 0;
  246.     bw data;
  247.     wl sweep;
  248.  
  249.     /* fetch params */
  250.     step = (int)(p->rate * 65.536);
  251.     depth = (int)(p->depth * (double)SampleRate / 1000.0);
  252.     delay = (int)(p->delay * (double)SampleRate / 1000.0);
  253.     
  254.     /* init/calc some stuff */
  255.     max_sweep = BFSZ - 2 - delay;
  256.     min_sweep = max_sweep - depth;
  257.     if(min_sweep < 0) {
  258.         printf("Can't do that much delay or depth at this sample rate.\n");
  259.         exit(1);
  260.     }
  261.     sweep.w[1] = (min_sweep + max_sweep) / 2;
  262.     sweep.w[0] = 0;
  263.  
  264.     /* init store and read ptrs to known value */
  265.     fp = ep1 = ep2 = 0;
  266.     
  267.     /* disable interrupts, go to it */
  268.     disable();
  269.     while(1) {
  270.         while((inp(SR) & 0x20) == 0);       /* wait for input ready */
  271.         data.b[0] = inp(PDR);               /* read input from chip */
  272.         data.b[1] = inp(PDR);
  273.  
  274.         /* interpolate from the 2 read values */
  275.         outval =
  276.          (Buf[ep1] * sweep.w[0] + Buf[ep2] * (ifac - sweep.w[0])) / ifac;
  277.         
  278.         /* store finished input plus feedback */
  279.         Buf[fp] = (inval = (double)data.w) + outval * p->feedback;
  280.         
  281.         /* develop final output mix */
  282.         outval = outval * p->wet_mix + inval * p->dry_mix;
  283.         if(outval > 32767.0)
  284.             data.w = 32767;
  285.         else if(outval < -32768.0)
  286.             data.w = -32768;
  287.         else
  288.             data.w = (int)outval;
  289.             
  290.         while((inp(SR) & 0x2) == 0);        /* wait for output ready */
  291.         outp(PDR,data.b[0]);                /* write output to chip */
  292.         outp(PDR,data.b[1]);
  293.         
  294.         /* update ptrs */
  295.         fp = (fp + 1) & (BFSZ - 1);
  296.         sweep.l += step;
  297.         ep1 = (fp + sweep.w[1]) & (BFSZ - 1);
  298.         ep2 = (ep1 - 1) & (BFSZ - 1);
  299.  
  300.         /* check for sweep reversal */      
  301.         if(sweep.w[1] > max_sweep)          /* see if we hit top of sweep */
  302.             step = -step;                   /* reverse */
  303.         else if(sweep.w[1] < min_sweep)     /* or if we hit bottom of sweep */
  304.             step = -step;                   /* reverse */
  305.             
  306.         check_human();                      /* check on human every so often */
  307.     }
  308. }
  309.  
  310. /*
  311.                                 pitch_change
  312.     
  313.     dry_mix     mix of unaffected signal (-0.999 to 0.999)
  314.     wet_mix     mix of affected signal (-0.999 - 0.999)
  315.     feedback    amount of recirculation (-0.9 - 0.9)
  316.     rate        amount of pitch change (see table below for values)
  317.     depth       sweep range in millisecs for generating pitch shift
  318.     delay       fixed additional delay
  319.  
  320.     Semitones      Up              Down
  321.         1       0.059463        -0.056126
  322.         2       0.122462        -0.109101
  323.         3       0.189207        -0.159104
  324.         4       0.259921        -0.206299
  325.         5       0.334840        -0.250846
  326.         6       0.414214        -0.292893
  327.         7       0.498307        -0.332580
  328.         8       0.587401        -0.370039
  329.         9       0.681793        -0.405396
  330.         10      0.781797        -0.438769
  331.         11      0.887749        -0.470268
  332.         12      1.000000        -0.500000
  333. */
  334. void
  335. pitch_change(register struct program *p)
  336. {
  337.     int fp,ep1,ep2,ep3,ep4;
  338.     int depth,delay,min_sweep,max_sweep,sweep_up;
  339.     int i,step,xfade,xfade_cnt,active,active_cnt,chanA;
  340.     long scan = 0;
  341.     double inval,outval,comp,ifac = 65536.0;
  342.     double blendA,blendB,*fadeA,*fadeB;
  343.     static double fade_out[MAX_XTAB],fade_in[MAX_XTAB];
  344.     bw data;
  345.     wl sweep;
  346.  
  347.     /* fetch params */
  348.     step = (int)(p->rate * 65535.0);
  349.     sweep_up = p->rate > 0;
  350.     depth = (int)(p->depth * (double)SampleRate / 1000.0);
  351.     delay = (int)(p->delay * (double)SampleRate / 1000.0);
  352.     xfade = (int)(12.0 * (double)SampleRate / 1000.0);
  353.     
  354.     /* init/calc some stuff */
  355.     max_sweep = BFSZ - 2 - delay;
  356.     min_sweep = max_sweep - depth;
  357.     active = max_sweep - min_sweep - (int)(xfade * p->rate) - 2;
  358.     if(xfade > MAX_XTAB) {
  359.         printf("Can't do pitch change crossfade at this sample rate.\n");
  360.         exit(1);
  361.     }
  362.     if(min_sweep < 0) {
  363.         printf("Can't do that much delay or depth at this sample rate.\n");
  364.         exit(1);
  365.     }
  366.             
  367.     /* build the crossfade lookup tables */
  368.     for(i = 0; i < xfade; i++) {
  369.         fade_in[i] = cos((double)i * M_PI_2 / (double)xfade);
  370.         fade_out[i] = sin((double)i * M_PI_2 / (double)xfade);
  371.     }
  372.     
  373.     /* init store and read ptrs to known value, chanA active 1st */
  374.     fp = ep3 = ep4 = xfade_cnt = 0;
  375.     sweep.l = 0;
  376.     if(sweep_up)
  377.         ep1 = ep2 = min_sweep;
  378.     else
  379.         ep1 = ep2 = max_sweep;
  380.     active_cnt = active;
  381.     blendA = 1.0;
  382.     blendB = 0.0;
  383.     fadeA = fade_out;
  384.     fadeB = fade_in;
  385.     chanA = TRUE;
  386.             
  387.     /* disable interrupts, go to it */
  388.     disable();
  389.     while(1) {
  390.         while((inp(SR) & 0x20) == 0);       /* wait for input ready */
  391.         data.b[0] = inp(PDR);               /* read input from chip */
  392.         data.b[1] = inp(PDR);
  393.  
  394.         /* messy expression to interpolate from both pairs of read ptrs */
  395.         comp = ifac - sweep.w[0];
  396.         outval =
  397.          ((Buf[ep1] * sweep.w[0] + Buf[ep2] * comp) * blendA +
  398.           (Buf[ep3] * sweep.w[0] + Buf[ep4] * comp) * blendB) / ifac;
  399.         
  400.         /* store finished input plus feedback */
  401.         Buf[fp] = (inval = (double)data.w) + outval * p->feedback;
  402.         
  403.         /* develop final output mix */
  404.         outval = outval * p->wet_mix + inval * p->dry_mix;
  405.         if(outval > 32767.0)                /* clip output if necessary */
  406.             data.w = 32767;
  407.         else if(outval < -32768.0)
  408.             data.w = -32768;
  409.         else
  410.             data.w = (int)outval;
  411.                         
  412.         while((inp(SR) & 0x2) == 0);        /* wait for output ready */
  413.         outp(PDR,data.b[0]);                /* write output to chip */
  414.         outp(PDR,data.b[1]);
  415.         
  416.         check_human();                      /* check on human every so often */
  417.  
  418.         /* see if crossfade active */
  419.         if(xfade_cnt) {
  420.             xfade_cnt--;
  421.             blendA = fadeA[xfade_cnt];
  422.             blendB = fadeB[xfade_cnt];
  423.         }
  424.         
  425.         /* update store ptr */
  426.         inc_index(fp);
  427.         
  428.         /* see which direction */
  429.         if(sweep_up) {
  430.             /* update sweep */
  431.             sweep.l += (unsigned)step;
  432.             
  433.             /* always inc at least once */
  434.             inc_indexes(ep1,ep2);
  435.             inc_indexes(ep3,ep4);
  436.             
  437.             /* if sweep didn't overflow, we're done */
  438.             if(sweep.w[1] == 0) continue;
  439.             
  440.             /* sweep overflowed, inc again */
  441.             inc_indexes(ep1,ep2);
  442.             inc_indexes(ep3,ep4);
  443.             sweep.w[1] = 0;
  444.             
  445.             /* see if it's time to switch over to other delay channel */
  446.             if(active_cnt-- == 0) {
  447.                 xfade_cnt = xfade;      /* initiate crossfade */
  448.                 active_cnt = active;    /* start counter on new channel */
  449.                 if(chanA) {             /* A has been active, go to B */
  450.                     chanA = FALSE;
  451.                     ep3 = (fp + min_sweep) & (BFSZ - 1);
  452.                     fadeA = fade_out;
  453.                     fadeB = fade_in;
  454.                 }
  455.                 else {
  456.                     chanA = TRUE;
  457.                     ep1 = (fp + min_sweep) & (BFSZ - 1);
  458.                     fadeB = fade_out;
  459.                     fadeA = fade_in;
  460.                 }
  461.             }
  462.         }
  463.         /* do downward sweep */
  464.         else {
  465.             sweep.l += step;            /* update sweep */
  466.             
  467.             /* if sweep didn't overflow, inc ptrs, that's all */
  468.             if(sweep.w[1] == 0) {
  469.                 inc_indexes(ep1,ep2);
  470.                 inc_indexes(ep3,ep4);
  471.                 continue;
  472.             }
  473.             /* sweep overflowed, check on stuff but skip ptr inc */         
  474.             sweep.w[1] = 0;
  475.             
  476.             /* see if it's time to switch over to other delay channel */
  477.             if(active_cnt-- == 0) {
  478.                 xfade_cnt = xfade;
  479.                 active_cnt = active;
  480.                 if(chanA) {             /* A has been active, go to B */
  481.                     chanA = FALSE;
  482.                     ep3 = (fp + max_sweep) & (BFSZ - 1);
  483.                     fadeA = fade_out;
  484.                     fadeB = fade_in;
  485.                 }
  486.                 else {
  487.                     chanA = TRUE;
  488.                     ep1 = (fp + max_sweep) & (BFSZ - 1);
  489.                     fadeB = fade_out;
  490.                     fadeA = fade_in;
  491.                 }
  492.             }
  493.         } /* end down sweep */
  494.     } /* end main loop */
  495. }
  496.  
  497. /*
  498.                                 phase_shift
  499.  
  500.     Digital version of the popular '70s effect.  This one
  501.     does 4 stages just like old MXR Phase 90 stompbox.
  502.     
  503.     dry_mix     mix of unaffected signal (-0.999 to 0.999)
  504.     wet_mix     mix of affected signal (-0.999 - 0.999)
  505.     feedback    amount of recirculation (-0.9 - 0.9)
  506.     rate        rate of sweep in cycles per second
  507.     depth       sweep range in octaves
  508.     delay       base frequency of sweep
  509. */
  510. void
  511. phase_shift(register struct program *p)
  512. {
  513.     long scan = 0;
  514.     double wp,min_wp,max_wp,range,coef,sweepfac;
  515.     double inval,x1,outval = 0.0;
  516.     static double lx1,ly1,lx2,ly2,lx3,ly3,lx4,ly4;
  517.     bw data;
  518.  
  519.     /* calc params for sweeping filters */  
  520.     wp = min_wp = (M_PI * p->delay) / (double)SampleRate;
  521.     range = pow(2.0,p->depth);
  522.     max_wp = (M_PI * p->delay * range) / (double)SampleRate;
  523.     p->rate = pow(range,p->rate / ((double)SampleRate / 2));
  524.     sweepfac = p->rate;
  525.     
  526.     /* disable interrupts, go to it */
  527.     disable();
  528.     while(1) {
  529.         coef = (1.0 - wp) / (1.0 + wp);     /* calc coef for current freq */
  530.         
  531.         while((inp(SR) & 0x20) == 0);       /* wait for input ready */
  532.         data.b[0] = inp(PDR);               /* read input from chip */
  533.         data.b[1] = inp(PDR);
  534.  
  535.         x1 = (inval = (double)data.w) + p->feedback * ly4;
  536.         ly1 = coef * (ly1 + x1) - lx1;      /* do 1st filter */
  537.         lx1 = x1;
  538.         ly2 = coef * (ly2 + ly1) - lx2;     /* do 2nd filter */
  539.         lx2 = ly1;
  540.         ly3 = coef * (ly3 + ly2) - lx3;     /* do 3rd filter */
  541.         lx3 = ly2;
  542.         ly4 = coef * (ly4 + ly3) - lx4;     /* do 4th filter */
  543.         lx4 = ly3;
  544.         
  545.         /* develop final output mix */
  546.         outval = ly4 * p->wet_mix + inval * p->dry_mix;
  547.         if(outval > 32767.0)                /* clip output if necessary */
  548.             data.w = 32767;
  549.         else if(outval < -32768.0)
  550.             data.w = -32768;
  551.         else
  552.             data.w = (int)outval;
  553.         
  554.         while((inp(SR) & 0x2) == 0);        /* wait for output ready */
  555.         outp(PDR,data.b[0]);                /* write output to chip */
  556.         outp(PDR,data.b[1]);
  557.  
  558.         wp *= sweepfac;                     /* adjust freq of filters */
  559.         if(wp > max_wp)                     /* max? */
  560.             sweepfac = 1.0 / p->rate;       /* sweep back down */
  561.         else if(wp < min_wp)                /* min? */
  562.             sweepfac = p->rate;             /* sweep back up */
  563.  
  564.         check_human();                      /* check on human every so often */
  565.     }
  566. }
  567.  
  568.  
  569. /*
  570.                                 chk_keystroke
  571.     
  572.     Sees if human has hit a key.  If so, exits.  This routine makes
  573.     a click cuz it has to turn on interrupts briefly.
  574. */
  575. void
  576. chk_keystroke(void)
  577. {
  578.     enable();
  579.     if(kbhit()) {
  580.         getch();
  581.         exit(0);
  582.     }
  583.     disable();
  584. }
  585.  
  586. /*
  587.                                 usage
  588. */
  589. void
  590. usage(void)
  591. {
  592.     int i;
  593.     static char *use = 
  594.     "Usage: fx [patch] [[samp_rate]] [[src_gain]]\n"
  595.     " patch       Selects effect program.  Value should be 0-%d.\n"
  596.     " samp_rate   Selects sampling frequency.  Value should be 5,6,8,\n"
  597.     "             9,11,16,18,22,27,32,33,37,44, or 48. Defaults to 16k.\n"
  598.     " src_gain    Selects source and gain.  0-15 adjust line input level.\n"
  599.     "             16-31 select the microphone input and adjust its level.\n"
  600.     "             Defaults to 23 for microphone input.\n";
  601.     
  602.     printf(use,NPROGS - 1);
  603.     for(i = 0; i < NPROGS; i++)
  604.         printf("Patch %2d:\t%s\n",i,programs[i].name);
  605.     exit(1);
  606. }
  607.  
  608.  
  609. int iar_mce;
  610.         
  611. /*
  612.                                 init_1848
  613.     
  614.     Sets up for programmed I/O at spec'd sample rate.  Initiates
  615.     simultaneous capture and play mode.
  616. */
  617. void
  618. init_1848(int samprate,int mic,int gain)
  619. {   
  620.     int i,version;
  621.     struct sr {
  622.         int handle;             /* handy value for humans */
  623.         unsigned int actual;    /* actual sample rate */
  624.         int code;               /* code for chip */
  625.     };
  626.     struct sr *srp;
  627.     struct sr sr_tab[NUM_SRATES] = {
  628.         {5,5152,S5152},     {6,6615,S6615},     {8,8000,S8000},
  629.         {9,9600,S9600},     {11,11025,S11025},  {16,16000,S16000},
  630.         {18,18900,S18900},  {22,22050,S22050},  {27,27428,S27428},
  631.         {32,32000L,S32000}, {33,33075L,S33075}, {37,37800L,S37800},
  632.         {44,44100L,S44100}, {48,48000L,S48000}};
  633.  
  634.     /* look up code for spec'd sample rate */   
  635.     for(i = 0, srp = sr_tab; i < NUM_SRATES; i++, srp++) {
  636.         if(srp->handle == samprate || srp->actual == samprate)
  637.             break;
  638.     }
  639.     if(i == NUM_SRATES) usage();
  640.                 
  641.     delay(0);                           /* calibrate delay routine */
  642.     
  643.     version = rd_reg(MISCINFO);         /* see what kind of chip we have */
  644.     if(version == 0xff) {
  645.         printf("Can't find 1848 chip.\n");
  646.         exit(1);
  647.     }
  648.     printf("Found AD1848%c CODEC\n",(version & 0xf) + 'A'); 
  649.     /* NOTE: the rev K chip is reportedly much quieter and worth getting */
  650.     
  651.     /* prepare to change/init chip setup */
  652.     wr_reg(LOUTCTL,0x80);               /* mute left DAC */
  653.     wr_reg(ROUTCTL,0x80);               /* mute right DAC */
  654.     wr_reg(DIGMIX,0);                   /* mute digital mix */
  655.     wr_reg(LAUX1CTL,0x80);              /* mute left aux1 in */
  656.     wr_reg(RAUX1CTL,0x80);              /* mute right aux1 in */
  657.     wr_reg(LAUX2CTL,0x80);              /* mute left aux2 in */
  658.     wr_reg(RAUX2CTL,0x80);              /* mute right aux2 in */
  659.     
  660.     /* change chip config */
  661.     outp(IAR,iar_mce = 0x40);           /* allow mode changes */
  662.     wr_reg(INTCFG,0xc8);                /* set auto calibrate */
  663.     wr_reg(CLKDATFMT,0x40 | srp->code);
  664.     
  665.     while(inp(IAR) & 0x80)              /* wait for chip to come out of init */
  666.         ;
  667.     
  668.     outp(IAR,iar_mce = 0x00);           /* clear mode change enable */
  669.     delay(2000);                        /* wait for auto calib to kick in */
  670.     
  671.     while(rd_reg(TSTINIT) & 0x20)       /* wait for auto calibration */
  672.         ;
  673.  
  674.     wr_reg(LOUTCTL,0);                  /* unmute the DACs */
  675.     wr_reg(ROUTCTL,0);
  676.     i = (mic ? 0xa0 : 0x40) | (gain & 0xf);/* decide gain and signal source */
  677.     wr_reg(LINCTL,i);                   /* unmute the inputs */
  678.     wr_reg(RINCTL,i);
  679.     wr_reg(INTCFG,0xc3);                /* kick off capture and play */
  680.     
  681.     printf("Sample rate initialized to %u.\n",srp->actual);
  682.     SampleRate = srp->actual;
  683. }
  684.  
  685. /*
  686.                                 wr_reg
  687. */
  688. void
  689. wr_reg(int reg, int val)
  690. {
  691.     outp(IAR,iar_mce | reg);
  692.     outp(IDR,val);
  693. }
  694.  
  695. /*
  696.                                 rd_reg
  697. */
  698. int
  699. rd_reg(int reg)
  700. {
  701.     outp(IAR,iar_mce | reg);
  702.     return(inp(IDR));
  703. }